Kubernetes Pod 无法终结问题
问题现象
某pod运行出现异常,被终结后一直无法正常退出,在kubernetes端的现象:
1 | root@h009028:~# kubectl get pods -o wide --all-namespaces | grep bsys | grep Ter |
pod一直处于Terminating状态
在docker端的现象:
1 | root@h009028:~# docker ps | grep bsys |
排查
1.尝试docker exec 进入容器内或执行命令,均失败:
1 | root@h009028:~# docker exec -it 6b7697bc161e bash |
原因是容器的初始pid已经被回收:
1 | root@h009028:~# ps -ef | grep 120770 |
2.查看docker daemon日志:
1 | root@h009028:~# journalctl -fu docker.service |
日志分析可以得知:
默认向容器发送的sig 15(SIGTREM)并没有使容器正常退出,10S后,执行SIGKILL使其强制退出,但实际的结果却是,SIGKILL也没能奏效,容器依然没有退出。
3.查看容器内现有未终结的进程
1 | root@h009028:~# docker top 6b7697bc161e |
发现容器内部应该作为PID 1的初始进程早已终结,但却有一些子进程还存在,应该就是这些进程导致容器无法彻底退出,查看它们的pid为121143的父进程的信息:
1 | root@h009028:~# ps -ef | grep 121143 |
1 |
|
此进程处于sleep状态,kill掉它和它的子进程:
1 | ps -ef | grep 121143 | awk '{print $2}' | xargs kill -s 9 |
再来查看一下容器状态:
1 | root@h009028:~# docker ps -a | grep bsys |
容器已退出
原因
容器内所有的其他进程都是pid 1号进程的子进程,正常情况下,pid收到sig 15退出后,会发送信号处理好依附自身的子进程,但偶然情况下还是会出现一些问题:父进程退出前,未来得及处理完容器内的子进程,导致它们变成了孤儿进程,而容器本身的pid 1号进程此时已经退出,docker daemon向其发送sig kill,此信号只针对pid 1的主进程,对这些孤儿进程不生效,从而导致了容器始终无法终结。处理了这些孤儿进程后,容器就可以正常退出了。